#!/usr/bin/env python3
"""
StarWeb 认证框架管理脚本
类似于Django的manage.py，提供数据库迁移、创建管理员、创建应用等功能
"""

import asyncio
import sys
import os
from pathlib import Path
import click
from typing import Optional

# 设置项目根目录
BASE_DIR = Path(__file__).parent.absolute()
os.chdir(BASE_DIR)

# 添加项目路径到sys.path
sys.path.insert(0, str(BASE_DIR))

from pkg.settings.config import settings


@click.group()
def cli():
    """StarWeb 认证框架管理工具"""
    pass


@cli.command()
def migrate():
    """执行数据库迁移"""
    click.echo("开始执行数据库迁移...")

    async def run_migration():
        from pkg.core.database.db import init_db, generate_schemas
        try:
            await init_db()
            await generate_schemas()
            click.echo("✓ 数据库迁移完成")
        except Exception as e:
            click.echo(f"✗ 数据库迁移失败: {e}")
            raise
        finally:
            from pkg.core.database.db import close_db
            await close_db()

    asyncio.run(run_migration())


def validate_email(ctx, param, value):
    """验证邮箱格式"""
    if '@' not in value:
        raise click.BadParameter('邮箱格式不正确，必须包含@符号')
    return value


def validate_password(ctx, param, value):
    """验证密码长度"""
    if len(value) < 6:
        raise click.BadParameter('密码至少需要6位字符')
    return value


@cli.command()
@click.option('--username', prompt='用户名', help='管理员用户名')
@click.option('--email', prompt='邮箱', callback=validate_email, help='管理员邮箱')
@click.option('--password', prompt='密码', hide_input=True, confirmation_prompt=True, callback=validate_password,
              help='管理员密码')
def createsuperuser(username: str, email: str, password: str):
    """创建超级管理员用户"""
    click.echo(f"正在创建超级管理员: {username}...")

    async def create_admin():
        from pkg.core.database.db import init_db, close_db
        from apps.auth.models.user import User

        try:
            await init_db()

            # 检查用户是否已存在
            existing_user = await User.filter(username=username).first()
            if existing_user:
                click.echo(f"✗ 用户名 '{username}' 已存在")
                return

            existing_email = await User.filter(email=email).first()
            if existing_email:
                click.echo(f"✗ 邮箱 '{email}' 已存在")
                return

            # 创建超级管理员
            user = User(
                username=username,
                email=email,
                is_superuser=True,
                is_verified=False,
                status=1  # UserStatusInt.ACTIVE
            )
            # 使用User模型的set_password方法加密密码
            user.set_password(password)
            await user.save()

            if user:
                click.echo(f"✓ 超级管理员 '{username}' 创建成功")
                click.echo(f"  用户ID: {user.id}")
                click.echo(f"  用户名: {user.username}")
                click.echo(f"  邮箱: {user.email}")
            else:
                click.echo("✗ 创建超级管理员失败")

        except Exception as e:
            click.echo(f"✗ 创建超级管理员失败: {e}")
            raise
        finally:
            await close_db()

    asyncio.run(create_admin())


@cli.command()
@click.argument('app_name')
def startapp(app_name: str):
    """创建新的应用模块"""
    click.echo(f"正在创建应用: {app_name}...")

    # 检查应用名是否合法
    if not app_name.isidentifier():
        click.echo(f"✗ 应用名 '{app_name}' 不是有效的Python标识符")
        return

    app_dir = BASE_DIR / "apps" / app_name

    # 检查应用目录是否已存在
    if app_dir.exists():
        click.echo(f"✗ 应用 '{app_name}' 已存在")
        return

    try:
        # 创建应用目录结构
        app_dir.mkdir(parents=True)
        (app_dir / "controllers").mkdir()
        (app_dir / "models").mkdir()
        (app_dir / "repositories").mkdir()
        (app_dir / "services").mkdir()
        (app_dir / "schemas").mkdir()

        # 创建__init__.py文件
        (app_dir / "__init__.py").write_text("", encoding='utf-8')
        (app_dir / "controllers" / "__init__.py").write_text("", encoding='utf-8')
        (app_dir / "models" / "__init__.py").write_text("", encoding='utf-8')
        (app_dir / "repositories" / "__init__.py").write_text("", encoding='utf-8')
        (app_dir / "services" / "__init__.py").write_text("", encoding='utf-8')
        (app_dir / "schemas" / "__init__.py").write_text("", encoding='utf-8')

        # 创建router.py文件
        router_content = f'''
from fastapi import APIRouter
from pkg.middlewares.auth_middleware import get_current_user
from fastapi import Depends

# 定义API前缀 - 这将被apps.py用于路由挂载
API_PREFIX = "/{app_name}"
# dependencies=[Depends(get_current_user)]
router = APIRouter()

# 导入所有控制器以注册路由（确保所有控制器中的路由都注册到这个router实例）
try:
    # 示例：导入控制器
    # from .controllers.{app_name}_controller import router as {app_name}_router
    # router.include_router({app_name}_router)
    pass
except ImportError as e:
    pass
'''
        (app_dir / "router.py").write_text(router_content.strip(), encoding='utf-8')

        # 创建示例控制器
        controller_content = f'''"""
{app_name} 控制器模块
处理 {app_name} 相关的HTTP请求
"""
from fastapi import APIRouter, Depends, Query
from typing import Optional
from pkg.middlewares.auth_middleware import get_current_user
from apps.auth.models.user import User

router = APIRouter()


@router.get("/", summary="获取{app_name}列表")
async def get_{app_name}_list(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    current_user: User = Depends(get_current_user)
):
    """获取{app_name}列表"""
    return {{"message": "获取{app_name}列表成功", "data": []}}


@router.get("/{{item_id}}", summary="获取{app_name}详情")
async def get_{app_name}_detail(
    item_id: int,
    current_user: User = Depends(get_current_user)
):
    """获取{app_name}详情"""
    return {{"message": "获取{app_name}详情成功", "data": {{"id": item_id}}}}
'''
        (app_dir / "controllers" / f"{app_name}_controller.py").write_text(controller_content, encoding='utf-8')

        click.echo(f"✓ 应用 '{app_name}' 创建成功")
        click.echo(f"  应用目录: {app_dir}")
        click.echo(f"  API前缀: /{app_name}")
        click.echo("\n请在应用的router.py中取消注释控制器导入代码以启用路由")

    except Exception as e:
        click.echo(f"✗ 创建应用失败: {e}")
        # 清理可能创建的文件
        if app_dir.exists():
            import shutil
            shutil.rmtree(app_dir)


@cli.command()
def runserver():
    """启动开发服务器"""
    click.echo(f"启动开发服务器在 {settings.HOST}:{settings.PORT}")
    import uvicorn

    uvicorn.run(
        "run:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=settings.RELOAD,
        workers=settings.WORKERS if settings.WORKERS > 0 else None,
        log_level=settings.LOG_LEVEL.lower(),
    )


@cli.command()
def listapps():
    """列出所有已注册的应用"""
    from apps.apps import app_registry

    apps = app_registry.discover_apps()

    click.echo("已发现的应用:")
    if not apps:
        click.echo("  (无)")
    else:
        for app in apps:
            click.echo(f"  - {app}")


@cli.command()
@click.option('--format', 'output_format', default='table', type=click.Choice(['table', 'json']), help='输出格式')
def showroutes(output_format: str):
    """显示所有路由信息"""
    from pkg.core.app import create_app

    app = create_app()
    routes = []

    for route in app.routes:
        if hasattr(route, 'methods') and hasattr(route, 'path'):
            for method in route.methods:
                if method != 'HEAD':
                    routes.append({
                        'method': method,
                        'path': route.path,
                        'name': getattr(route, 'name', ''),
                        'tags': getattr(route, 'tags', [])
                    })

    if output_format == 'json':
        import json
        click.echo(json.dumps(routes, indent=2, ensure_ascii=False))
    else:
        click.echo(f"共找到 {len(routes)} 个路由:")
        click.echo(f"{'方法':<8} {'路径':<30} {'标签':<15} {'名称'}")
        click.echo("-" * 70)
        for route in routes:
            tags_str = ', '.join(route['tags']) if route['tags'] else ''
            click.echo(f"{route['method']:<8} {route['path']:<30} {tags_str:<15} {route['name']}")


# @cli.command()
# def shell():
#     """启动交互式Python shell"""
#     import code

#     # 导入常用模块
#     from apps.auth.models.user import User
#     from apps.auth.services.user_service import UserService
#     from pkg.core.database.db import init_db, close_db

#     async def async_shell():
#         await init_db()

#         # 准备shell环境
#         namespace = {
#             'User': User,
#             'UserService': UserService,
#             'settings': settings,
#         }

#         click.echo("StarWeb 交互式Shell")
#         click.echo("可用对象: User, UserService, settings")
#         click.echo("注意: 数据库已连接，使用完毕后请手动调用 await close_db()")

#         # 启动交互式shell
#         code.interact(local=namespace)

#         await close_db()

#     asyncio.run(async_shell())


if __name__ == '__main__':
    cli()
